/**
 * $Id: Staff.java 89 2012-12-28 10:57:30Z Denis.Skalsky@gmail.com $
 */
package com.globallogic.skalskyy.javabasic.valstaff;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.globallogic.skalskyy.javabasic.valstaff.commands.InformationCollector;

/**
 * Staff is a list of employee.
 * @author $Author: Denis.Skalsky@gmail.com $
 * @version $Revision: 89 $
 */
public class Staff {
	
	/** Primary key for employee */
	private static int currentId = 0;
	private List<Employee> list = new ArrayList<Employee>();
	private static Staff instace;
	
	private Staff() {}
	
	private List<Employee> findBy(String criteria, Matcher matcher) {
		List<Employee> result = new ArrayList<Employee>();
		
		for (Employee employee : list) {
			if (matcher.match(criteria, employee)) {
				result.add(employee);
			}
		}
		
		return result;		
	}

	private List<String> getCommonInfo(InformationCollector informationCollector) {
		List<String> info = new ArrayList<String>();
		
		for (Employee employee : list) {
			informationCollector.collect(info, employee);
		}		
		Collections.sort(info);
		
		return info;
	}
	
	public static Staff getInstance() {
		if (instace == null) {
			instace = new Staff();
		}
		
		return instace;
	}
	
	/**
	 * Get count of employees
	 * @return count of employees
	 */
	public int getCount() {
		return list.size();
	}
	
	public List<Employee> getList() {
		return list;
	}

	public void add(Employee employee) {
		list.add(employee);
		Staff.currentId++;
		employee.setId(Staff.currentId);
	}	
	
	public List<Employee> findBySecondName(String secondName) {
		return this.findBy(
				secondName,
				new Matcher() {
					
					@Override
					public boolean match(String criteria, Employee employee) {
						return employee.compareSecondName(criteria); 
					}
				});
	}

	public List<Employee> findByFirstName(String firstName) {
		return this.findBy(
				firstName,
				new Matcher() {
					
					@Override
					public boolean match(String criteria, Employee employee) {
						return (employee.compareFirstName(criteria));
					}
				});
	}

	public List<Employee> findByPosition(String position) {
		return this.findBy(
				position,
				new Matcher() {
					
					@Override
					public boolean match(String criteria, Employee employee) {
						return (employee.comparePosition(criteria));
					}
				});
	}

	public List<Employee> findByLanguage(String language) {
		return this.findBy(
				language,
				new Matcher() {
					
					@Override
					public boolean match(String criteria, Employee employee) {
						if (employee instanceof SoftwareEngineer) {
							return ((SoftwareEngineer)employee).compareLanguage(criteria);
						} else {
						return false;
						}
					}
				});
	}

	public List<Employee> findByTesterType(String testerType) {
		return this.findBy(
				testerType, 
				new Matcher() {
					
					@Override
					public boolean match(String criteria, Employee employee) {
						if (employee instanceof TestEngineer) {
							return ((TestEngineer)employee).compareType(criteria);
						} else {
							return false;
						}
					}
				});
	}

	public List<Employee> findByDateOfBirth(String date) {
		return this.findBy(
				date,
				new Matcher() {
					
					@Override
					public boolean match(String criteria, Employee employee) {						
						return employee.compareDateOfBirth(criteria);
					}
				});
	}

	public List<String> getPositions() {
		return getCommonInfo(new InformationCollector() {
			
			@Override
			public void collect(List<String> info, Employee employee) {
				if (info.indexOf(employee.getPosition()) == -1) {
					info.add(employee.getPosition());
				}				
			}
		});
	}

	public List<String> getSoftwareEngineers() {
		return getCommonInfo(new InformationCollector() {
			
			@Override
			public void collect(List<String> info, Employee employee) {
				if (employee instanceof SoftwareEngineer) {
					info.add(employee.toString());
				}				
			}
		});
	}

	public List<String> getTestEngineers() {
		return getCommonInfo(new InformationCollector() {
			
			@Override
			public void collect(List<String> info, Employee employee) {
				if (employee instanceof TestEngineer) {
					info.add(employee.toString());
				}				
			}
		});
	}

	public void clear() {
		list.clear();
		currentId = 0;		
	}
}